package com.vladmr.sleepytimepicker;

import java.util.Calendar;

import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.AlarmClock;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.NumberPicker;
import android.widget.NumberPicker.OnValueChangeListener;
import android.widget.SimpleCursorAdapter;
import android.widget.SimpleCursorAdapter.ViewBinder;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.TimePicker.OnTimeChangedListener;
import android.widget.Toast;

import com.vladmr.sleepytimepicker.provider.SleepyTimeProvider;

public class ChooseWakeupActivity extends Activity {
	private static final String TAG = "sleepytimepicker";
	private static final Uri CONTENT_URI = Uri
			.parse("content://com.vladmr.sleepytimepicker.provider.sleepytimeprovider");
	private static final String PATH_WAKEUP = "wakeup";

	protected AppPreferences appPrefs;

	// you are going to go to bed after this time
	int offsetHour, offsetMinute;

	// step in minute timepicker
	int minuteStep = 10;

	public static Uri buildWakeupUri() {
		return CONTENT_URI.buildUpon().appendPath(PATH_WAKEUP).build();
	}

	public static Uri buildWakeupIdUri(String str_id) {
		return CONTENT_URI.buildUpon().appendPath(PATH_WAKEUP)
				.appendPath(str_id).build();
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.choose_wakeup_activity);

		if (android.os.Build.VERSION.SDK_INT >= 11) {
			ActionBar actionBar = getActionBar();
			actionBar.setDisplayHomeAsUpEnabled(true);
		}

		appPrefs = new AppPreferences(getApplicationContext());
		offsetHour = appPrefs.getOffsetHour();
		offsetMinute = appPrefs.getOffsetMinute();

		if (android.os.Build.VERSION.SDK_INT >= 11) {
			InitTimePicker11();
		} else {
			InitTimePicker9();
		}
		InitListView();
	}

	@Override
	public void onResume() {
		super.onResume();

		if (android.os.Build.VERSION.SDK_INT >= 11) {
			SetTimePicker11();
		} else {
			TimePicker timepicker = (TimePicker) findViewById(R.id.timepicker7);
			timepicker.setCurrentHour(offsetHour);
			timepicker.setCurrentMinute(offsetMinute);
		}
	}

	@Override
	protected void onPause() {
		SaveOffsetInPrefs();
		super.onPause();
	}

	private void SaveOffsetInPrefs() {
		appPrefs.setOffset(offsetHour, offsetMinute);
	}

	/**
	 * timepicker API9
	 */
	private void InitTimePicker9() {
		TimePicker timepicker = (TimePicker) findViewById(R.id.timepicker7);
		timepicker.setIs24HourView(true);
		// disable popup keyboard
		timepicker
				.setDescendantFocusability(TimePicker.FOCUS_BLOCK_DESCENDANTS);

		timepicker.setOnTimeChangedListener(new OnTimeChangedListener() {
			@Override
			public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
				int hourchanged = hourOfDay - offsetHour;
				int minutechanged = minute - offsetMinute;

				// Log.i(TAG, "ontimechanged start: offsethour = " + offsetHour
				// + ", offsetminute = " + offsetMinute);
				// Log.i(TAG, "ontimechanged start: hourchange = " + hourchanged
				// + ", minutechange = " + minutechanged);

				// updated screen only in the last call
				if (hourchanged == 0 && minutechanged == 0) {
					SaveOffsetInPrefs();
					UpdateLayout();
				} else {

					if (hourchanged == 1 || hourchanged == -1) {
						if (hourOfDay > 5) {
							offsetHour = 5;
							Toast.makeText(
									getApplicationContext(),
									"it's too much time range to predict, please come back later :)",
									Toast.LENGTH_SHORT).show();
						} else {
							offsetHour = offsetHour + hourchanged;
						}
						view.setCurrentHour(offsetHour);
					} else if (hourchanged == 23) {
						offsetHour = 0;
						view.setCurrentHour(offsetHour);
					}

					// add minutes
					if (minutechanged == 1) {
						offsetMinute = offsetMinute + minuteStep;
						if (offsetMinute >= 60) {
							offsetMinute = offsetMinute - 60;
							if (offsetHour < 5) {
								offsetHour = offsetHour + 1;
								view.setCurrentHour(offsetHour);
							} else {
								Toast.makeText(
										getApplicationContext(),
										"it's too much time range to predict, please come back later :)",
										Toast.LENGTH_SHORT).show();
							}
						}
						view.setCurrentMinute(offsetMinute);

						// remove minutes
					} else if (minutechanged == -1 || minutechanged == 59) {
						offsetMinute = offsetMinute - minuteStep;
						if (offsetMinute < 0) {
							offsetMinute = offsetMinute + 60;
							if (offsetHour > 0) {
								offsetHour = offsetHour - 1;
								view.setCurrentHour(offsetHour);
							} else {
								offsetMinute = 0;
								Toast.makeText(
										getApplicationContext(),
										"you could not fall asleep earlier than now :(",
										Toast.LENGTH_SHORT).show();
							}
						}
						view.setCurrentMinute(offsetMinute);
					}
				}
			}
		});
	}

	/**
	 * timepicker API11
	 */
	private void InitTimePicker11() {
		NumberPicker pickerHour = (NumberPicker) findViewById(R.id.numberPickerHour);
		NumberPicker pickerMinute = (NumberPicker) findViewById(R.id.numberPickerMinute);

		// disable popup keyboard
		pickerHour
				.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
		pickerMinute
				.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

		pickerHour.setOnValueChangedListener(new OnValueChangeListener() {

			@Override
			public void onValueChange(NumberPicker picker, int oldVal,
					int newVal) {
				offsetHour = newVal;
				SaveOffsetInPrefs();
				UpdateLayout();
			}
		});

		pickerMinute.setOnValueChangedListener(new OnValueChangeListener() {

			@Override
			public void onValueChange(NumberPicker picker, int oldVal,
					int newVal) {
				int value = newVal * minuteStep;
				offsetMinute = value;
				SaveOffsetInPrefs();
				UpdateLayout();
			}
		});
	}

	private void SetTimePicker11() {
		NumberPicker pickerHour = (NumberPicker) findViewById(R.id.numberPickerHour);
		NumberPicker pickerMinute = (NumberPicker) findViewById(R.id.numberPickerMinute);

		pickerHour.setMinValue(0);
		pickerHour.setMaxValue(5);
		pickerHour.setValue(offsetHour);

		String[] minutes = new String[6];
		for (int i = 0; i < minutes.length; i++) {
			int value = i * minuteStep;
			if (value < 10) {
				minutes[i] = "0" + Integer.toString(value);
			} else {
				minutes[i] = Integer.toString(value);
			}

		}
		pickerMinute.setMinValue(0);
		pickerMinute.setMaxValue(minutes.length - 1);
		pickerMinute.setDisplayedValues(minutes);
		pickerMinute.setValue(offsetMinute / minuteStep);
		UpdateLayout();
	}

	private void InitListView() {
		final ListView lv = (ListView) findViewById(R.id.listview);
		lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int index,
					long arg3) {
				if (android.os.Build.VERSION.SDK_INT >= 9) {
					Cursor cursor = (Cursor) lv.getItemAtPosition(index);
					int position = cursor.getInt(cursor.getColumnIndex("_ID"));

					SetAlarm(position);
				}
			}
		});
	}

	/**
	 * launch AlarmClock application (if API >= 9)
	 */
	private void SetAlarm(int position) {
		Calendar alarm = GetWakeupTime(position);
		// launch AlarmClock application
		Intent setAlarm = new Intent(AlarmClock.ACTION_SET_ALARM);
		setAlarm.putExtra(AlarmClock.EXTRA_MESSAGE, "new alarm");
		setAlarm.putExtra(AlarmClock.EXTRA_HOUR,
				alarm.get(Calendar.HOUR_OF_DAY));
		setAlarm.putExtra(AlarmClock.EXTRA_MINUTES, alarm.get(Calendar.MINUTE));

		Log.i(TAG,
				"alarm set: "
						+ FormatTime(alarm.get(Calendar.HOUR_OF_DAY),
								alarm.get(Calendar.MINUTE)));
		startActivity(setAlarm);
	}

	private Calendar GetWakeupTime(int position) {
		// An array specifying which columns to return.
		String columns[] = new String[] { SleepyTimeProvider.Columns.ID,
				SleepyTimeProvider.Columns.TIME_FALLASLEEP,
				SleepyTimeProvider.Columns.TIME_WAKEUP };
		Uri uri = buildWakeupIdUri(String.valueOf(position));
		Cursor cursor = getContentResolver().query(uri, columns, // Which
																	// columns
																	// to
																	// return
				null, // WHERE clause; which rows to return(all rows)
				null, // WHERE clause selection arguments (none)
				null // Order-by clause (ascending by name)
				);
		if (cursor.moveToFirst()) {
			Calendar wakeup_time = Calendar.getInstance();
			wakeup_time.setTimeInMillis(cursor.getLong(2));
			return wakeup_time;
		} else {
			return null;
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (android.os.Build.VERSION.SDK_INT >= 11) {
			switch (item.getItemId()) {
			case android.R.id.home:
				// app icon in action bar clicked; go home
				Intent intent = new Intent(this, MainActivity.class);
				intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
				startActivity(intent);
				return true;
			}
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * update the screen after timePickerDuration changed
	 */
	@SuppressWarnings("deprecation")
	private void UpdateLayout() {
		ListView lv = (ListView) findViewById(R.id.listview);

		// An array specifying which columns to return.
		String columns[] = new String[] { SleepyTimeProvider.Columns.ID,
				SleepyTimeProvider.Columns.TIME_FALLASLEEP,
				SleepyTimeProvider.Columns.SLEEPYTIME,
				SleepyTimeProvider.Columns.TIME_WAKEUP };

		Uri myUri = buildWakeupUri();
		Cursor cursor = getContentResolver().query(myUri, columns, // Which
																	// columns
																	// to return
				null, // WHERE clause; which rows to return(all rows)
				null, // WHERE clause selection arguments (none)
				null // Order-by clause (ascending by name)
				);

		// THE DESIRED COLUMNS TO BE BOUND
		String[] lv_columns = new String[] {
				SleepyTimeProvider.Columns.SLEEPYTIME,
				SleepyTimeProvider.Columns.TIME_WAKEUP };

		// THE XML DEFINED VIEWS WHICH THE DATA WILL BE BOUND TO
		int[] to = new int[] { R.id.item_sleepy, R.id.item_time };

		// CREATE THE ADAPTER USING THE CURSOR POINTING TO THE DESIRED DATA AS
		// WELL AS THE LAYOUT INFORMATION
		SimpleCursorAdapter adapter;
		if (android.os.Build.VERSION.SDK_INT >= 11) {
			adapter = new SimpleCursorAdapter(this, R.layout.wakeup_item,
					cursor, lv_columns, to, 0);
		} else {
			adapter = new SimpleCursorAdapter(this, R.layout.wakeup_item,
					cursor, lv_columns, to);
		}
		adapter.setViewBinder(new ViewBinder() {

			@Override
			public boolean setViewValue(View view, Cursor cursor,
					int columnIndex) {
				// columnIndex based on all columns in cursor
				String str_textview = "";
				try {
					long timeinmillis = cursor.getLong(columnIndex);
					Calendar calendar = Calendar.getInstance();
					calendar.setTimeInMillis(timeinmillis);
					switch (columnIndex) {
					case 2:
						str_textview = FormatTimeToText(
								calendar.get(Calendar.HOUR_OF_DAY),
								calendar.get(Calendar.MINUTE));
						break;
					case 3:
						str_textview = FormatTime(
								calendar.get(Calendar.HOUR_OF_DAY),
								calendar.get(Calendar.MINUTE));
						break;
					}
				} catch (Exception e) {
					str_textview = cursor.getString(columnIndex);
				}

				TextView textView = (TextView) view;
				textView.setText(str_textview);
				return true;
			}
		});
		lv.setAdapter(adapter);

		// highlight recommended sleepy time duration
		// int adaptercount = adapter.getCount();
		// if (adaptercount >= highlightitem) {
		// View item = adapter.getView(highlightitem, null, null);
		// // item.setAlpha(0);
		// item.setBackgroundColor(getResources().getColor(
		// R.color.default_light));
		// }
	}

	// format calendar object into readable form: 7:30
	private String FormatTime(int hourOfDay, int minute) {
		String output = "";
		if (minute >= 10) {
			output = hourOfDay + ":" + minute;
		} else {
			output = hourOfDay + ":0" + minute;
		}
		return output;
	}

	// format calendar object into readable form: 7h 30min
	private String FormatTimeToText(int hourOfDay, int minute) {
		String output = "";
		if (minute > 0) {
			output = hourOfDay + getString(R.string.hour) + " " + minute
					+ getString(R.string.minute);
		} else {
			output = hourOfDay + getString(R.string.hour);
		}
		return output;
	}
}
